import AgoraRTC from 'agora-rtc-sdk'
import { roomStore } from './room'
import { globalStore } from './global'
import { t } from '../i18n/i18n'

const ENABLE_LOG = false // 是否上传日志
if (ENABLE_LOG) {
  // 打开日志
  AgoraRTC.Logger.enableLogUpload()
  AgoraRTC.Logger.setLogLevel(AgoraRTC.Logger.DEBUG)
} else {
  // 关闭日志
  AgoraRTC.Logger.disableLogUpload()
  AgoraRTC.Logger.setLogLevel(AgoraRTC.Logger.NONE)
}

const streamEvents = [
  'accessAllowed',
  'accessDenied',
  'stopScreenSharing',
  'videoTrackEnded',
  'audioTrackEnded',
  'player-status-changed'
]

export class AgoraStream {
  stream = ''
  streamID = ''
  local = ''
}

export default class AgoraRTCClient {
  constructor() {
    this.streamID = 0
    this._init = false
    this._joined = false
    this._published = false
    this._internalTimer = null
    this._client = null
    this._localStream = null
    this._streamEvents = []
    this._clientEvents = []
    this._addEventListener = false
  }

  // init rtc client when _init flag is false;
  // 初始化客户端
  async initClient({ uid, channel, token, appId }) {
    if (this._init) return
    this._client = AgoraRTC.createClient({ mode: 'live', codec: 'vp8' })
    this._client.init(appId, () => {
      this.subscribeClientEvents()
      this.join(+uid, channel, token)
    })
  }

  // 加入频道
  join(uid, channel, token) {
    this._client.join(
      token,
      channel,
      uid,
      () => {
        console.log('加入频道成功')
      },
      err => {
        console.error(err, '加入频道失败')
      }
    )
  }

  // 初始化音视频流对象
  async createLocalStream(uid) {
    this._localStream = AgoraRTC.createStream({
      streamID: uid,
      audio: true,
      video: true,
      mirror: false,
      screen: false
    })
    return new Promise((resolve, reject) => {
      this._localStream.init(
        () => {
          this.streamID = uid
          console.log('初始化音视频流对象')
          this.publish()
          this.subscribeLocalStreamEvents()
          resolve()
        },
        err => {
          reject(err)
        }
      )
    })
  }

  // 发布音视频
  async publishLocalStream(data) {
    console.log(' publish local stream ', this._published)
    if (this._published) {
      await this.unpublishLocalStream()
      console.log('[agora-web] unpublished', this._published)
    }

    if (!data.cameraId || !data.microphoneId) {
      let { devices } = await this.getDevices()
      if (!data.cameraId) {
        data.cameraId = devices.filter(it => it.kind === 'videoinput')[0].deviceId
      }
      if (!data.microphoneId) {
        data.microphoneId = devices.filter(it => it.kind === 'audioinput')[0].deviceId
      }
    }

    await this.createLocalStream(data.streamID)
    await this.publish()
    this._published = true
  }

  // 停止
  async unpublishLocalStream() {
    console.log('[agora-web] invoke unpublishStream')
    await this.unpublish()
    this._published = false
  }

  // 监听rtc-Client
  subscribeClientEvents() {
    this._client.on('stream-added', args => {
      this._client.subscribe(args.stream, err => {
        console.error('Subscribe stream failed ', 'error', err)
      })
    })

    this._client.on('stream-published', args => {
      let _stream = {
        stream: args.stream,
        uid: args.stream.getId(),
        local: true
      }
      roomStore.addLocalStream(_stream)
      roomStore.addRTCUser(args.stream.getId())
    })
    this._client.on('stream-subscribed', args => {
      let _stream = {
        stream: args.stream,
        uid: args.stream.getId(),
        local: false
      }
      roomStore.addRemoteStream(_stream)
    })
    this._client.on('stream-removed', args => {
      roomStore.removeRemoteStream(args.stream.getId())
    })
    this._client.on('peer-online', args => {
      roomStore.addRTCUser(args.uid)
    })
    this._client.on('peer-leave', args => {
      roomStore.removePeerUser(args.uid)
      roomStore.removeRemoteStream(args.uid)
      if (roomStore.state.me.role === 1 && roomStore.state.course.roomType === 2) {
        if (roomStore.state.applyUser.account) {
          globalStore.showToast({
            type: 'rtmClient',
            message: t('toast.student_peer_leave', { reason: roomStore.state.applyUser.account })
          })
        }
      }
    })

    this._client.on('removestream', args => {
      roomStore.removePeerUser(args.uid)
      roomStore.removeRemoteStream(args.uid)
    })

    this._client.on('client-role-changed', args => {
      console.log(args)
    })
  }

  // 监听rtc-stream
  subscribeLocalStreamEvents() {
    for (let evtName of streamEvents) {
      this._streamEvents.push(evtName)
      this._localStream.on(`${evtName}`, args => {
        console.log(args)
      })
    }
  }

  // 取消事件绑定
  unsubscribeClientEvents() {
    if (this._addEventListener) {
      for (let evtName of this._clientEvents) {
        this._client.off(evtName, () => {})
        this._clientEvents = this._clientEvents.filter(it => it === evtName)
      }
      this._addEventListener = false
    }
  }

  // 发布本地音视频流
  async publish() {
    return new Promise((resolve, reject) => {
      if (this._published) {
        return resolve()
      }
      this._client.publish(
        this._localStream,
        () => {
          console.log('发布本地音视频流')
        },
        err => {
          console.error(err)
          reject(err)
        }
      )
      setTimeout(() => {
        resolve()
        this._published = true
      }, 300)
    })
  }

  // 取消发布本地音视频流
  unpublish() {
    return new Promise((resolve, reject) => {
      if (!this._published || !this._localStream) {
        return resolve()
      }
      this._client.unpublish(this._localStream, err => {
        console.error(err)
        reject(err)
      })
      setTimeout(() => {
        resolve()
        this.destroyLocalStream()
        this._published = false
      }, 300)
    })
  }

  // 开启双流模式。双流为视频大流和视频小流，其中视频大流指高分辨率、高码率的视频流，视频小流指低分辨率、低码率的视频流。
  enableDualStream() {
    return new Promise((resolve, reject) => {
      this._client.enableDualStream(resolve, reject)
    })
  }

  // 设置视频大小流
  setRemoteVideoStreamType(stream, streamType) {
    this._client.setRemoteVideoStreamType(stream, streamType)
  }

  // 更新 Token
  renewToken(newToken) {
    if (!this._client) return console.warn('renewToken is not permitted, checkout your instance')
    this._client.renewToken(newToken)
  }

  // 删除
  removeAllListeners() {
    this.unsubscribeClientEvents()
  }

  // 播放音视频
  playLocalStream(domId) {
    if (!this._localStream || (!this.streamID && this._localStream.isPlaying())) return
    this._localStream.play(`dom-${domId}`, { fit: 'cover' })
  }

  // 销毁音视频流
  destroyLocalStream() {
    this.unsubscribeLocalStreamEvents()
    if (this._localStream) {
      if (this._localStream.isPlaying()) {
        this._localStream.stop()
      }
      this._localStream.close()
    }
    this._localStream = null
    this.streamID = 0
  }

  unsubscribeLocalStreamEvents() {
    if (this._localStream) {
      for (let evtName of this._streamEvents) {
        this._localStream.removeEventListener(evtName, args => {})
        this._streamEvents = this._streamEvents.filter(it => it === evtName)
      }
    }
  }

  // 离开频道
  leave() {
    if (this._client) {
      /* return new Promise((resolve, reject) => {
        this._client.leave(resolve, reject)
        this._client = null
      }) */
      this._client.leave(() => {
        this.destroyLocalStream()
        this._client = null
      })
    }
  }

  // 设置音频输出设备，可以在麦克风和扬声器之间切换
  setAudioOutput(speakerId) {
    return new Promise((resolve, reject) => {
      if (this._client) {
        this._client.setAudioOutput(speakerId, resolve, reject)
        return
      }
      resolve()
    })
  }

  // 调节播放订阅流的音量大小
  setAudioVolume(volume) {
    this._client.setAudioVolume(volume)
  }

  // 接收远端音视频流
  subscribe(stream) {
    this._client.subscribe(stream, { video: true, audio: true }, err => {
      console.log('[rtc-client] subscribe failed: ', JSON.stringify(err))
    })
  }

  // 销毁房间
  destroy() {
    this._internalTimer && clearInterval(this._internalTimer)
    this._internalTimer = null
    this.destroyLocalStream()
    this.removeAllListeners()
  }

  destroyClient() {
    this.unsubscribeClientEvents()
  }

  // 退出房间
  exit() {
    try {
      this.leave()
    } catch (err) {
      return err
    } finally {
      this.destroy()
    }
  }

  // 获取可用的媒体输入/输出设备
  getDevices() {
    return new Promise((resolve, reject) => {
      AgoraRTC.getDevices(
        devices => {
          const _devices = []
          devices.forEach(item => {
            _devices.push({ deviceId: item.deviceId, kind: item.kind, label: item.label })
          })
          resolve({
            cameraCanUse: devices.filter(it => it.kind === 'videoinput').length > 0 ? true : false,
            microphoneCanUse:
              devices.filter(it => it.kind === 'audioinput').length > 0 ? true : false,
            devices: _devices
          })
        },
        err => {
          reject(err)
        }
      )
    })
  }

  // 创建音视频流对象
  forceGetDevices() {
    const tempAudioStream = AgoraRTC.createStream({ audio: true, video: false })
    const tempVideoStream = AgoraRTC.createStream({ audio: false, video: true })

    const audioPermissionOK = new Promise(resolve => {
      tempAudioStream.init(
        () => resolve(null),
        err => resolve(err)
      )
    })
    const videoPermissionOK = new Promise(resolve => {
      tempVideoStream.init(
        () => resolve(null),
        err => resolve(err)
      )
    })

    try {
      let [microphone, camera] = Promise.all([audioPermissionOK, videoPermissionOK])
      let result = this.getDevices()

      if (microphone !== null) {
        result.microphoneCanUse = false
        console.warn('create audio temp stream failed!', microphone)
      }
      if (camera !== null) {
        result.cameraCanUse = false
        console.warn('create video temp stream failed!', camera)
      }

      return result
    } catch (err) {
      return err
    } finally {
      tempAudioStream.close()
      tempVideoStream.close()
    }
  }
}
